package tech.bmatch.redpack.service.impl;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import tech.bmatch.common.util.IDUtil;
import tech.bmatch.redpack.model.*;
import tech.bmatch.redpack.param.CreateRedPackParam;
import tech.bmatch.redpack.service.RedPackService;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 红包服务的实现类
 */
@Component
public class RedPackServiceImpl implements RedPackService {

    private static final Logger logger = LoggerFactory.getLogger(RedPackServiceImpl.class);

    /**
     * 红包的缓存
     */
    private static List<RedPack> caches = new ArrayList<>();

    private static Map<String, Merchant> merchantCache = new HashMap<>();

    /**
     * 我领取的红包缓存
     */
    private static Map<String,List<MyRedPack>> myRedPackCache = new HashMap();

    private static Map<String,SharedRedPack> sharedRedPackCache = new HashMap<>();

    private static Map<String,List<MySharedRedPack>> mySharedRedPackCache = new HashMap<>();

    static {
        merchantCache.put("test001",new Merchant("test001","肯德基","//p1.meituan.net/msmerchant/db00fab658c3661fc92ec793627684cd64503.jpg@275w_156h_1e_1c"));
        merchantCache.put("test002", new Merchant("test002","麦当劳","//p0.meituan.net/mogu/0a6af6a9acdc84bb26e8fab8d6a250bc111664.png@275w_156h_1e_1c"));
        merchantCache.put("test003", new Merchant("test003","院子餐厅","//p0.meituan.net/feop/d91337976e8f9540e31caaff3eeffd3c57619.png@275w_156h_1e_1c"));
    }

    @Override

    public RedPack create(CreateRedPackParam createRedPackParam) {
        RedPack redPack = null;

        if (createRedPackParam.getCouponType().equals(CouponType.MONEYOFF)) {
            MonenyOffRedPack monenyOffRedPack = new MonenyOffRedPack();
            initRedPack(createRedPackParam, monenyOffRedPack);
            monenyOffRedPack.setTotalAmount(createRedPackParam.getTotalAmount() * 100);
            monenyOffRedPack.setMerchantId(createRedPackParam.getMerchantId());
            redPack = monenyOffRedPack;
        } else {
            redPack = new RedPack();
            initRedPack(createRedPackParam, redPack);
        }

        caches.add(redPack);
        return redPack;
    }

    private void initRedPack(CreateRedPackParam createRedPackParam, RedPack redPack) {
        redPack.setId(IDUtil.getId());
        redPack.setGmtCreated(new Date());
        redPack.setGmtModified(new Date());
        redPack.setCouponType(createRedPackParam.getCouponType());
        redPack.setType(createRedPackParam.getRedPackType());
        redPack.setValidity(createRedPackParam.getValidity());
        redPack.setAmount(createRedPackParam.getAmount() * 100);


        List<RedPackCondition> conditions = new ArrayList<>();
        redPack.setConditions(conditions);

        createRedPackParam.getConditionIds().forEach(id -> {
            RedPackCondition condition = new RedPackCondition();
            condition.setId(id);
            conditions.add(condition);
        });
    }

    @Override
    public List<RedPack> query(RedPackType redPackType) {
        List<RedPack> list = caches.stream().filter(redPack -> redPack.getType().equals(redPackType)).collect(Collectors.toList());

        list.stream().filter(redPack -> redPack.getCouponType().equals(CouponType.MONEYOFF)).forEach(redPack -> {
            MonenyOffRedPack monenyOffRedPack = (MonenyOffRedPack) redPack;
            Merchant merchant = merchantCache.get(monenyOffRedPack.getMerchantId());

            monenyOffRedPack.setMerchantName(merchant.getName());
            monenyOffRedPack.setMerchantLogo(merchant.getLogo());
        });
        return list;
    }

    @Override
    public List<MyRedPack> rainPack(String userId) {
        if(userId==null){
            return null;
        }

        List<MyRedPack> myRedPackList = myRedPackCache.get(userId);
        if (myRedPackList == null){
            myRedPackList = new ArrayList<>();
            myRedPackCache.put(userId,myRedPackList);
        }

        long redpackCount = myRedPackList.stream().filter(myRedPack -> DateUtils.isSameDay(new Date(),myRedPack.getGmtCreated())).count();

        if(redpackCount>0){
            return null;
        }

        List<RedPack> redPacks = query(RedPackType.VOUCHER);
        List<MyRedPack> result = new ArrayList<>();
        Calendar cal = Calendar.getInstance();
        redPacks.stream().limit(3).forEach(redPack -> {
        MyRedPack myRedPack = new MyRedPack();

        myRedPack.setId(IDUtil.getId());
        myRedPack.setGmtModified(new Date());
        myRedPack.setGmtCreated(new Date());
        myRedPack.setUserId(userId);
        myRedPack.setRedPack(redPack);

        cal.add(Calendar.DAY_OF_MONTH,redPack.getValidity());
        myRedPack.setValidityDay(cal.getTime());
        cal.clear();
        result.add(myRedPack);
        });

        myRedPackList.addAll(result);

        return result;
    }

    @Override
    public SharedRedPack createSharedPack(SharedRedPack sharedRedPack) {

        if(sharedRedPack == null){
            return null;
        }
        if(StringUtils.isEmpty(sharedRedPack.getSharedUserId())){
            logger.error("the sharedRedPack userId is null or empty");
            return null;
        }
        if(sharedRedPack.getMaxAmount()==0){
            logger.error("the sharedRedPack need maxAmount");
            return null;
        }

        if(sharedRedPack.getMaxIndex() == 0){
            logger.error("the sharedRedPack need maxIndex");
            return null;
        }

        Date date = new Date();
        sharedRedPack.setId(IDUtil.getId());
        sharedRedPack.setGmtModified(date);
        sharedRedPack.setGmtCreated(date);
        sharedRedPack.setMaxAmount(sharedRedPack.getMaxAmount()*100);

        sharedRedPackCache.put(sharedRedPack.getId(),sharedRedPack);

        return sharedRedPack;
    }

    @Override
    public List<MySharedRedPack> grabPack(String sharedRedPackId,String userId) {

        List<MySharedRedPack> mySharedRedPacks = mySharedRedPackCache.get(sharedRedPackId);

        if(mySharedRedPacks == null){
            mySharedRedPacks = new ArrayList<>();
            mySharedRedPackCache.put(sharedRedPackId,mySharedRedPacks);

        }

       boolean hasMySharedRedPack = mySharedRedPacks.stream()
               .filter(pack->pack.getMyRedPack().getUserId().equals(userId)).findFirst().isPresent();

        if(hasMySharedRedPack){
            return mySharedRedPacks;
        }

        MySharedRedPack mySharedRedPack = new MySharedRedPack();

        SharedRedPack sharedRedPack = sharedRedPackCache.get(sharedRedPackId);

        mySharedRedPack.setSharedRedPack(sharedRedPack);
        mySharedRedPack.setId(IDUtil.getId());
        mySharedRedPack.setGmtModified(new Date());
        mySharedRedPack.setGmtCreated(new Date());
        mySharedRedPack.setIndex(mySharedRedPacks.size()+1);

        MyRedPack myRedPack = createRedPack(userId, mySharedRedPack, sharedRedPack);

        mySharedRedPack.setMyRedPack(myRedPack);

        mySharedRedPacks.add(mySharedRedPack);


        return mySharedRedPacks;
    }

    private MyRedPack createRedPack(String userId, MySharedRedPack mySharedRedPack, SharedRedPack sharedRedPack) {
        RedPack redPack = new RedPack();
        redPack.setType(RedPackType.CASH);
        redPack.setCouponType(CouponType.CASH);
        redPack.setId(IDUtil.getId());
        redPack.setGmtModified(new Date());
        redPack.setGmtCreated(new Date());
        redPack.setValidity(3);

        if(mySharedRedPack.getIndex()<sharedRedPack.getMaxIndex()){
           redPack.setAmount((int)(Math.random()*2+1)*100);
        }
        else if(mySharedRedPack.getIndex() == sharedRedPack.getMaxIndex()){
            redPack.setAmount(sharedRedPack.getMaxAmount());
        }else{
            redPack.setAmount(50);
        }


        MyRedPack myRedPack = new MyRedPack();
        myRedPack.setId(IDUtil.getId());
        myRedPack.setGmtModified(new Date());
        myRedPack.setGmtCreated(new Date());
        myRedPack.setUserId(userId);
        myRedPack.setRedPack(redPack);

        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_MONTH,redPack.getValidity());
        myRedPack.setValidityDay(cal.getTime());

        myRedPackCache.compute(userId,(key,val)->{
            if(val==null){
                val = new ArrayList<>();
            }
            val.add(myRedPack);
            return val;
        });
        return myRedPack;
    }

}
